projectiles = {} -- array to keep track of projectiles

function newProj(piid,pibm,ir,ig,ib,pdmg,pheight,pwidth,pspeed,pname,prng,penrgy,pexp)
	local proj={}
	proj = {
		iid = image(piid,0,0,1),
		dmg = pdmg,
		height = pheight,
		width = pwidth,
		speed = pspeed,
		name = pname,
		range = prng,
		energyr = penrgy,
		explode = pexp,
	}
	imageblend(proj.iid,pibm)
	imagecolor(proj.iid,ir,ig,ib)
	return proj
end

function checkEmpty(v)
    for i = 1, #projectiles do
        if projectiles[i] == "obsolete" then
            projectiles[i] = v
            return i
        end
    end
    projectiles[#projectiles + 1] = v
	return #projectiles
end

function doublearray(m,n,k)
	local a, x, y = {}
	for x = 0, m do a[x] = {}
		for y = 0, n do
			a[x][y] = k
		end
	end
	return a
end

map_array = doublearray(map("xsize"),map("ysize"),false)  -- used to store a true/false version of the map, if there is a wall, true, if an obstacle or floor, false.

function init_projectile_map_array() -- place this in a function that is called every map change/round restart/equivalent
	for x = 0, map("xsize") do
		for y = 0, map("ysize") do
			if tile(x,y,"wall") then
				map_array[x][y] = true
			else
				map_array[x][y] = false
			end
		end
	end
end

function positive(n) -- lol... :P
	return math.abs(n) == n
end

function distance(x1,y1,x2,y2)
	return ((x1-x2)^2 + (y1-y2)^2)^0.5
end

function createProjectile(proj,shooter,x,y,rot,speed,target_id) -- See Note 1 btw, x,y is the players coord, it will point more forward to not explode when fired
	if target_id ~= nil and target_id ~= 0 then
		proj.homing = target_id
	else
		proj.homing = 0
		proj.x_inc = math.cos(math.rad(rot)) * speed
		proj.y_inc = math.sin(math.rad(rot)) * speed
	end
	proj.shooter = shooter
	proj.x = x + math.cos(math.rad(rot))*10+((proj.width+proj.height)/2) + 1
	proj.y = y + math.cos(math.rad(rot))*10+((proj.width+proj.height)/2) + 1
	proj.rot = rot
	proj.speed = speed
	proj.ccr = (proj.width + proj.height)/2 -- this is a radius to a collision circle
	proj.tid = target_id
	proj.txinc = 0
	proj.tyinc = 0
	proj.tspd = 0
	proj.trot = 0
	proj.drot = 0
	proj.ox = x
	proj.oy = y
	proj.pid = checkEmpty(proj)
end

function removeProjectile(pid)
	for k,v in pairs(projectiles) do
		if ( pid == k and v ~= "obsolete" ) then
			freeimage(v.iid)
			projectiles[k] = "obsolete"
			break
		end
	end
end

function isProjectileColliding(x,y,explode,shooter,dmg,name,speed,ccr,tid,rot)
		
		local nextx,nexty = x,y --+ math.cos(math.rad(rot))*speed, y+ math.sin(math.rad(rot))*speed
		--local nextx,nexty = x+ math.cos(math.rad(rot))*speed, y+ math.sin(math.rad(rot))*speed
		if (x>0 and y>0 and x<(map("xsize")*32) and y<(map("ysize")*32)) then
			if( map_array[math.floor(x/32)][math.floor(y/32)] == true or tile(math.floor(x/32),math.floor(y/32),"frame")~=0) then
				if explode then
					parse("explosion "..nextx.." "..nexty.." 20 100 "..shooter)
				end
				elib.sound3("space/armhit.wav",nextx,nexty,1024)
				return true
			end
		end
		for _,id in pairs( player(0,"tableliving") ) do
			if distance(player(id,"x"),player(id,"y"),nextx,nexty) <= 10 + ccr + 1 and id~=shooter then
				if explode then
					parse("explosion "..nextx.." "..nexty.." 20 100 "..shooter)
				else
					if dmg == "kill" then
						parse("customkill "..shooter.." \""..name.."\" "..id)
					else
						if (not pstack.docked[id]) then
							local odmg=dmg
							local fdmg=0
							if (shipt[id]~="ms") then
								if (shield[id]>dmg*0.5) then
									shield[id]=shield[id]-math.ceil(dmg*0.5)
									restoringshield[id]=false
									freetimer("parse","lua restoringshield["..id.."]=true")
									timer(5000,"parse","lua restoringshield["..id.."]=true")
									shieldimg[id]=image("gfx/sprites/wave.bmp",1,0,200+id)
									imageblend(shieldimg[id],1)
									imagecolor(shieldimg[id],90,255,90)
									imagealpha(shieldimg[id],0)
									imagescale(shieldimg[id],5,5)
									tween_alpha(shieldimg[id],100,1)
									timer(100,"parse","lua tween_alpha("..shieldimg[id]..",100,0)")
									elib.sound3("space/shieldhit.ogg",player(id,"x"),player(id,"y"),1024)
								else
									fdmg=dmg-dmg*0.5
									if (fdmg>0) then
										armor[id]=armor[id]-fdmg
										elib.sound3("space/armhit.wav",player(id,"x"),player(id,"y"),1024)
									end
									shield[id]=0
									restoringshield[id]=false
									freetimer("parse","lua restoringshield["..id.."]=true")
									timer(5000,"parse","lua restoringshield["..id.."]=true")
									if (armor[id]>dmg) then
										armor[id]=armor[id]-dmg
										elib.sound3("space/armhit.wav",player(id,"x"),player(id,"y"),1024)
									else
										armor[id]=0
										fdmg=dmg-fdmg
										if (fdmg>0) then
											if (fdmg<player(id,"health")) then
												parse("sethealth "..id.." "..player(id,"health")-math.ceil(dmg*2))
											else
												parse("customkill "..shooter.." \""..name.."\" "..id)
											end
										end
										if (player(id,"health")>dmg*2) then
											parse("sethealth "..id.." "..player(id,"health")-math.ceil(dmg*2))
										end
									end
								end
							else
								if (inParty[id][1]) then
									if (parties[inParty[id][2]].mshipsh>dmg*0.5) then
										parties[inParty[id][2]].mshipsh=parties[inParty[id][2]].mshipsh-math.ceil(dmg*0.5)
										restoringshield[id]=false
										freetimer("parse","lua restoringshield["..id.."]=true")
										timer(5000,"parse","lua restoringshield["..id.."]=true")
										shieldimg[id]=image("gfx/sprites/wave.bmp",1,0,200+id)
										imageblend(shieldimg[id],1)
										imagecolor(shieldimg[id],255,90,90)
										imagealpha(shieldimg[id],0)
										imagescale(shieldimg[id],15,15)
										tween_alpha(shieldimg[id],100,1)
										timer(100,"parse","lua tween_alpha("..shieldimg[id]..",100,0)")
										elib.sound3("space/shieldhit.ogg",player(id,"x"),player(id,"y"),1024)
										return 1
									else
										fdmg=dmg-dmg*0.5
										if (fdmg>0) then
											parties[inParty[id][2]].mshipar=parties[inParty[id][2]].mshipar-fdmg
											elib.sound3("space/armhit.wav",player(id,"x"),player(id,"y"),1024)
											return 1
										end
										shield[id]=0
										restoringshield[id]=false
										freetimer("parse","lua restoringshield["..id.."]=true")
										timer(5000,"parse","lua restoringshield["..id.."]=true")
										if (parties[inParty[id][2]].mshipar>dmg) then
											parties[inParty[id][2]].mshipar=parties[inParty[id][2]].mshipar-dmg
											elib.sound3("space/armhit.wav",player(id,"x"),player(id,"y"),1024)
											return 1
										else
											parties[inParty[id][2]].mshipar=0
											fdmg=dmg-fdmg
											if (fdmg>0) then
												if (fdmg<player(id,"health")) then
													parse("sethealth "..id.." "..player(id,"health")-math.ceil(dmg*2))
													return 1
												else
													parse("customkill "..shooter.." \""..name.."\" "..id)
													return 1
												end
											end
											if (player(id,"health")>dmg*2) then
												parse("sethealth "..id.." "..player(id,"health")-math.ceil(dmg*2))
												return 1
											end
											return 1
										end
										return 1
									end
								end
							end
						end
					end
				end
				return true
			end
		end
	
end

addhook("always","update_projectiles")
function update_projectiles()
	for k,p in pairs(projectiles) do
		if p and p~="obsolete" then
			
			p.txinc = p.x_inc
			p.tyinc = p.y_inc
			if ((p.x + p.txinc)>0 and (p.y + p.tyinc)>0) then
				p.x = p.x + p.txinc
				p.y = p.y + p.tyinc
				imagepos(p.iid,p.x,p.y,p.rot-90)
				if (distance(p.ox,p.oy,p.x,p.y)>=p.range) then
					removeProjectile(p.pid)
					return
				end
			else
				removeProjectile(p.pid)
				return
			end
			if isProjectileColliding(p.x,p.y,p.explode,p.shooter,p.dmg,p.name,p.speed,p.ccr,p.rot) then -- (x,y,explode,shooter,dmg,name,ccr)
				removeProjectile(p.pid)
			end
		end
	end
end

init_projectile_map_array()